
#include "asm/stx7200reg.h"
#include "../../../cpu/sh/init_ram.S"

/*
 * This is derived from STMicroelectronics gnu toolchain example:
 *   sh-superh-elf/examples/os21/romdynamic/memory_mb519.S
 */

/*
 * The poke table is a series of long words, in the format
 *
 *       opcode, address, operand, ...
 *
 * An opcode of 0 marks the table end
 */


	.section .data.init, "a"

	.balign 32

__memory_setup_table:

  /* ----- STx7200 Clocks ----- */

  /* Set CLOCKGENA PLL0 into BYPASS... */
  OR_LONG(STX7200_CLOCKGENA_PLL0_CFG, 0x00100000)

  /* Power down CLOCKGENA PLL0... */
  OR_LONG(STX7200_CLOCKGENA_POWER_CFG, 0x00000001)

  /* Configure CLOCKGENA PLL0... */
  UPDATE_LONG(STX7200_CLOCKGENA_PLL0_CFG, 0xfff80000, 0x03 | (0x23 << 8) | (0x00 << 16))

  /* Enable CLOCKGENA PLL0... */
  UPDATE_LONG(STX7200_CLOCKGENA_POWER_CFG, 0xfffffffe, 0)

  /* Wait for CLOCKGENA PLL0 to lock... */
  WHILE_NE(STX7200_CLOCKGENA_PLL0_CFG, 0x80000000, 0x80000000)

  /* Clear CLOCKGENA PLL0 from BYPASS... */
  UPDATE_LONG(STX7200_CLOCKGENA_PLL0_CFG, 0xffefffff, 0)

  /* Set CLOCKGENA PLL1 into BYPASS... */
  OR_LONG(STX7200_CLOCKGENA_PLL1_CFG, 0x00100000)

  /* Power down CLOCKGENA PLL1... */
  OR_LONG(STX7200_CLOCKGENA_POWER_CFG, 0x00000002)

  /* Configure CLOCKGENA PLL1... */
  UPDATE_LONG(STX7200_CLOCKGENA_PLL1_CFG, 0xfff80000, 0x01 | (0x0f << 8))

  /* Enable CLOCKGENA PLL1... */
  UPDATE_LONG(STX7200_CLOCKGENA_POWER_CFG, 0xfffffffd, 0)

  /* Wait for CLOCKGENA PLL1 to lock... */
  WHILE_NE(STX7200_CLOCKGENA_PLL1_CFG, 0x80000000,  0x80000000)

  /* Clear CLOCKGENA PLL1 from BYPASS... */
  UPDATE_LONG(STX7200_CLOCKGENA_PLL1_CFG, 0xffefffff, 0)

  /* Set CLOCKGENA PLL2 into BYPASS... */
  OR_LONG(STX7200_CLOCKGENA_PLL2_CFG, 0x00100000)

  /* Power down CLOCKGENA PLL2... */
  OR_LONG(STX7200_CLOCKGENA_POWER_CFG, 0x00000004)

  /* Configure CLOCKGENA PLL2... */
  UPDATE_LONG(STX7200_CLOCKGENA_PLL2_CFG, 0xfff80000, 0x03 | (0x28 << 8) | (0x00 << 16))

  /* Enable CLOCKGENA PLL2... */
  UPDATE_LONG(STX7200_CLOCKGENA_POWER_CFG, 0xfffffffb, 0)

  /* Wait for CLOCKGENA PLL2 to lock... */
  WHILE_NE(STX7200_CLOCKGENA_PLL2_CFG, 0x80000000,  0x80000000)

  /* Clear CLOCKGENA PLL2 from BYPASS... */
  UPDATE_LONG(STX7200_CLOCKGENA_PLL2_CFG, 0xffefffff, 0)

  /* Set CLOCKGENB PLL0 into BYPASS... */
  OR_LONG(STX7200_CLOCKGENB_PLL0_CFG, 0x00100000)

  /* Power down CLOCKGENB PLL0... */
  OR_LONG(STX7200_CLOCKGENB_POWER_CFG, 0x00008000)

  /* Configure CLOCKGENB PLL0... */
  UPDATE_LONG(STX7200_CLOCKGENB_PLL0_CFG, 0xfff80000, 0x03 | (0x28 << 8) | (0x00 << 16))

  /* Enable CLOCKGENB PLL0... */
  UPDATE_LONG(STX7200_CLOCKGENB_POWER_CFG, 0xffff7fff, 0)

  /* Wait for CLOCKGENB PLL0 to lock... */
  WHILE_NE(STX7200_CLOCKGENB_PLL0_CFG, 0x80000000, 0x80000000)

  /* Clear CLOCKGENB PLL0 from BYPASS... */
  UPDATE_LONG(STX7200_CLOCKGENB_PLL0_CFG, 0xffefffff, 0)

  /* Power down PLL... */
  OR_LONG(STX7200_SYSCONF_SYS_CFG11, 0x00001000)

  /* Configure PLL... */
  /* Set LMI clock to 666MHz */
  UPDATE_LONG(STX7200_SYSCONF_SYS_CFG11, 0xfffff001, (0x05 << 9) | (0x6f << 1))
  /* On PCB rev A, we have a limitation on LMI1: Reset LMI clock to 400MHz */
  IF(0xa5020000, 0x000000ff, 0x0000000a, UPDATE_LONG(STX7200_SYSCONF_SYS_CFG11, 0xfffff001, (0x03 << 9) | (0x28 << 1)))

  /* Enable CLOCKGENA PLL1... */
  UPDATE_LONG(STX7200_SYSCONF_SYS_CFG11, 0xffffefff, 0)

  /* Wait for CLOCKGENA PLL1 to lock... (polarity inverted on lock bit) */
  WHILE_NE(STX7200_SYSCONF_SYS_STA03, 0x00000001, 0)

  /* ----- STx7200 Sysconf ----- */

  /* Exit from reset */
  OR_LONG(STX7200_SYSCONF_SYS_CFG11, 0x00000001)
  OR_LONG(STX7200_SYSCONF_SYS_CFG15, 0x00000001)

  /* Check both DLL on LMI0 are locked */
  WHILE_NE(STX7200_SYSCONF_SYS_STA03, (1 << 10) | (1 << 20), (1 << 10) | (1 << 20))

  /* Check both DLL on LMI1 are locked */
  WHILE_NE(STX7200_SYSCONF_SYS_STA05, (1 << 10) | (1 << 20), (1 << 10) | (1 << 20))

  /* Adjust proga, progb, zoutproga, and receiver mode for LMI0 */
  POKE_LONG(STX7200_SYSCONF_SYS_CFG12, 0xa2007801 | (0x0 << 1) | (0x7 << 4) | (0x7 << 7) | (0x0 << 10))

  /* Adjust proga, progb, zoutproga, and receiver mode for LMI1 */
  POKE_LONG(STX7200_SYSCONF_SYS_CFG16, 0xa2007801 | (0x0 << 1) | (0x7 << 4) | (0x7 << 7) | (0x0 << 10))

  /* Enable AutoPrecharge */
  OR_LONG(STX7200_SYSCONF_SYS_CFG38, 0x00030000)
  OR_LONG(STX7200_SYSCONF_SYS_CFG39, 0x00030000)

  /* Force DLL1 and DLL2 commands of LMI0 */
  POKE_LONG(STX7200_SYSCONF_SYS_CFG13, 0x00000002)
  POKE_LONG(STX7200_SYSCONF_SYS_CFG14, 0x00000002)

  /* Force DLL1 and DLL2 commands of LMI1 */
  POKE_LONG(STX7200_SYSCONF_SYS_CFG17, 0x00000002)
  POKE_LONG(STX7200_SYSCONF_SYS_CFG18, 0x00000002)

  /* ----- STx7200 EMI configuration ----- */

  POKE_LONG(ST40_EMI_BANK_ENABLE, 0x00000005)

  /* NOTE: bits [0,5] define bottom address bits [22,27] of bank */
  POKE_LONG(ST40_EMI_BANK0_BASEADDRESS, 0x00000000)
  POKE_LONG(ST40_EMI_BANK1_BASEADDRESS, 0x00000008)
  POKE_LONG(ST40_EMI_BANK2_BASEADDRESS, 0x0000000c)
  POKE_LONG(ST40_EMI_BANK3_BASEADDRESS, 0x00000010)
  POKE_LONG(ST40_EMI_BANK4_BASEADDRESS, 0x00000014)

  /* Bank 0 - On-board 32MiB Flash at address 0x00000000 -> 0x01ffffff */
  POKE_LONG(ST40_EMI_BANK0_EMICONFIGDATA0, 0x001016d1)
  POKE_LONG(ST40_EMI_BANK0_EMICONFIGDATA1, 0x9d200000)
  POKE_LONG(ST40_EMI_BANK0_EMICONFIGDATA2, 0x9d220000)
  POKE_LONG(ST40_EMI_BANK0_EMICONFIGDATA3, 0x00000000)

  /* Bank 2 - DVB-CI at address 0x03000000 -> 0x03FFFFFF */
  POKE_LONG(ST40_EMI_BANK2_EMICONFIGDATA0, 0x002046f9)
  POKE_LONG(ST40_EMI_BANK2_EMICONFIGDATA1, 0xa5a00000)
  POKE_LONG(ST40_EMI_BANK2_EMICONFIGDATA2, 0xa5a20000)
  POKE_LONG(ST40_EMI_BANK2_EMICONFIGDATA3, 0x00000000)

  /* Bank 4 - EPLD Registers at address 0x05000000 -> 0x05FFFFFF */
  POKE_LONG(ST40_EMI_BANK4_EMICONFIGDATA0, 0x042086f1)
  POKE_LONG(ST40_EMI_BANK4_EMICONFIGDATA1, 0x8a002200)
  POKE_LONG(ST40_EMI_BANK4_EMICONFIGDATA2, 0x8a004200)
  POKE_LONG(ST40_EMI_BANK4_EMICONFIGDATA3, 0x00000000)

  /* Program other EMI registers */
  POKE_LONG(ST40_EMI_GENCFG, 0x00000050)

  /* ----- STx7200 LMI0 configuration ----- */

  /* "Refresh Interval" is set equal to 0xA28=2600 => 2600*3ns=7.8us */
  POKE_LONG(ST40_LMI_MIM_0(0), 0x0a28015b)
  POKE_LONG(ST40_LMI_MIM_1(0), 0x000000b0)

  POKE_LONG(ST40_LMI_STR_0(0), 0xcb2cab5b)
  POKE_LONG(ST40_LMI_STR_1(0), 0x000002d6)

  /* lmi base address 0x08000000 + 128MiB 13x10 */
  POKE_LONG(ST40_LMI_SDRA0_0(0), 0x10000a00)

  /* lmi base address 0x08000000 + 128MiB 13x10 */
  POKE_LONG(ST40_LMI_SDRA1_0(0), 0x10000a00)

  /* Enable clock with NOP command */
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020023)
  /* Wait NOP command for 400 nsec */
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)

  /* Precharge all */
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020022)
  /* Wait NOP command for 400 nsec */
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)

  /* Issue EMRS2 */
  POKE_LONG(ST40_LMI_SDMR0(0), 0x00000800)

  /* Issue EMRS3 */
  POKE_LONG(ST40_LMI_SDMR0(0), 0x00000c00)

  /* Issue EMRS1 to enable DLL */
  POKE_LONG(ST40_LMI_SDMR0(0), 0x00000400)

  /* Issue MRS with DLL reset(0), CAS 5(0), Write recovery 6(0), Sequentiel(0), Burst lengh 8 */
  POKE_LONG(ST40_LMI_SDMR0(0), 0x00002353)

  /* Wait NOP command for 400 nsec */
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)

  /* Precharge all */
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020022)
  /* 2 CBR (auto refresh) */
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020024)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020024)

  /* Issue MRS with CAS 5(0), Write recovery 6(0), Sequentiel(0), Burst lengh 8 */
  POKE_LONG(ST40_LMI_SDMR0(0), 0x00002253)

  /* Issue EMRS1 for OCD calibration default */
  POKE_LONG(ST40_LMI_SDMR0(0), 0x000007c4)

  /* Issue EMRS1 for OCD calibration exit */
  POKE_LONG(ST40_LMI_SDMR0(0), 0x00000444)

  /* Enable auto refresh */
  POKE_LONG(ST40_LMI_MIM_0(0), 0x0a28035b)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(0), 0x00020021)

  POKE_LONG(ST40_LMI_GCC_0(0), 0x00382003)

  /* ----- STx7200 LMI1 configuration ----- */

  /* "Refresh Interval" is set equal to 0xA28=0d2600 => 2600*3ns=7.8us */
  POKE_LONG(ST40_LMI_MIM_0(1), 0x0a28015b)
  POKE_LONG(ST40_LMI_MIM_1(1), 0x000000b0)

  POKE_LONG(ST40_LMI_STR_0(1), 0xcb2cab5b)
  POKE_LONG(ST40_LMI_STR_1(1), 0x000002d6)

  /* lmi base address 0x18000000 + 64MiB 13x10 (all 128MiB are not visible in 29bits mode) */
  POKE_LONG(ST40_LMI_SDRA0_0(1), 0x1c000a00)

  /* lmi base address 0x18000000 + 64MiB 13x10 (all 128MiB are not visible in 29bits mode) */
  POKE_LONG(ST40_LMI_SDRA1_0(1), 0x1c000a00)

  /* Enable clock with NOP command */
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020023)
  /* Wait NOP command for 400 nsec */
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)

  /* Precharge all */
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020022)
  /* Wait NOP command for 400 nsec */
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)

  /* Issue EMRS2 */
  POKE_LONG(ST40_LMI_SDMR0(1), 0x00000800)

  /* Issue EMRS3 */
  POKE_LONG(ST40_LMI_SDMR0(1), 0x00000c00)

  /* Issue EMRS1 to enable DLL */
  POKE_LONG(ST40_LMI_SDMR0(1), 0x00000400)

  /* Issue MRS with DLL reset(1), CAS 5(1), Write recovery 6(1), Sequentiel(1), Burst lengh 8 */
  POKE_LONG(ST40_LMI_SDMR0(1), 0x00002353)

  /* Wait NOP command for 400 nsec */
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)

  /* Precharge all */
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020022)
  /* 2 CBR (auto refresh) */
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020024)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020024)

  /* Issue MRS with CAS 5(1), Write recovery 6(1), Sequentiel(1), Burst lengh 8 */
  POKE_LONG(ST40_LMI_SDMR0(1), 0x00002253)

  /* Issue EMRS1 for OCD calibration default */
  POKE_LONG(ST40_LMI_SDMR0(1), 0x000007c4)

  /* Issue EMRS1 for OCD calibration exit */
  POKE_LONG(ST40_LMI_SDMR0(1), 0x00000444)

  /* Enable auto refresh */
  POKE_LONG(ST40_LMI_MIM_0(1), 0x0a28035b)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)
  POKE_LONG(ST40_LMI_SCR_0(1), 0x00020021)

  POKE_LONG(ST40_LMI_GCC_0(1), 0x00382003)

#ifdef CONFIG_SH_SE_MODE
  /*
   * Note that we also manually need to move the LMI0 and LMI1 base addresses to
   * their 32-bit SE mode locations as defined in the datasheet and change the
   * 'upper bound addresses' (in row attribute registers) for the LMIs.
   */
  UPDATE_LONG(STX7200_SYSCONF_SYS_CFG38, 0xFFFFFF00, 0x00000040)
  UPDATE_LONG(STX7200_SYSCONF_SYS_CFG39, 0xFFFFFF00, 0x00000080)
  POKE_LONG(ST40_LMI_SDRA0_0(0), 0x48000a00)
  POKE_LONG(ST40_LMI_SDRA1_0(0), 0x48000a00)
  POKE_LONG(ST40_LMI_SDRA0_0(1), 0x88000a00)
  POKE_LONG(ST40_LMI_SDRA1_0(1), 0x88000a00)
#endif	/* CONFIG_SH_SE_MODE */

	END_MARKER

__memory_setup_table_end:

	.end
